package tests;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import model.Email;
import model.Filter;
import model.Folder;
import model.Meeting;
import model.ModelException;
import model.Template;
import model.Token;
import model.User;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.mockito.Mockito.*;

/**
 * This class tests the User class functionality
 * 
 * @author b_aldosa
 * @since June 16, 2013
 *
 */
public class TestUser {

	User user,mockedUser;
	Token token,mockedToken;
	Folder folder,mockedFolder;
	Filter filter;
	Email email;
	Meeting meeting;
	List<Folder> liftOfFolders;
	List<Email> listOfEmails;
	List<Filter> liftOfFilters;
	List<Meeting> liftOfMeetings,listOfMeetings2;
	List<Template> liftOfTemplates,listOfTemplates2;
	Template template;
	HashMap<String, String> properties;
	
	/**
	 * This method is called before every test case, its sets up the 
	 * mock objects and other objects needed in the tests
	 */
	@Before
	public void setUp()
	{
		user=new User("Buthainah");
		mockedToken=mock(Token.class);
		mockedUser=mock(User.class);
		token=new Token(1,"key","value");
		template=new Template(1,"title","body");
		meeting=new Meeting();
		filter=new Filter();
		email=new Email();
		folder=new Folder("folderName",1,1);
		listOfEmails=new ArrayList<Email>();
		liftOfFolders=new ArrayList<Folder>();
		liftOfFilters=new ArrayList<Filter>();
		liftOfMeetings=new ArrayList<Meeting>();
		listOfMeetings2=new ArrayList<Meeting>();
		liftOfTemplates=new ArrayList<Template>();
		listOfTemplates2=new ArrayList<Template>();
		properties=new HashMap<String, String> ();
		properties.put("Name", "Buthainah");
		properties.put("Id", "-1");
		user.setTemplates(liftOfTemplates);
		user.setMeetings(liftOfMeetings);
		
	}
	
	/**
	 * This method is called after every test case to nullify the objects
	 */
	@After
	public void tearDown()
	{
		user=null;
		token=null;
		template=null;
		meeting=null;
		filter=null;
		email=null;
		listOfEmails=null;
		liftOfFolders=null;
		liftOfFilters=null;
		liftOfMeetings=null;
		listOfMeetings2=null;
		liftOfTemplates=null;
		listOfTemplates2=null;
		
	}
	
	/**
	 * This test case tests the get id method
	 */
	@Test
	public void testGetId() {
	
		assertEquals(-1,user.getId());
	}
	/**
	 * This tests the get name method
	 */
	@Test
	public void testGetName() {
		assertEquals("Buthainah", user.getName());
	}
	/**
	 * This tests the test set name method
	 */
	@Test
	public void testSetName() {
		user.setName("New name");
		assertEquals("New name",user.getName());
	}
	/**
	 * This tests the load user method
	 * @throws ModelException
	 */
	@Test
	public void testLoad() throws ModelException {
		when(mockedUser.load("Buthainah")).thenReturn(true);
		assertEquals(true,mockedUser.load("Buthainah"));	
	}
	/**
	 * This tests the set properties method
	 */
	@Test
	public void testSetProperties() {
		user.setProperties(properties);
		assertEquals("Buthainah", user.getName());
		assertEquals(-1,user.getId());
	}
	/**
	 * This tests the create new folder method
	 * @throws ModelException
	 */
	@Test
	public void testCreateNewFolder() throws ModelException {
		when(mockedUser.createNewFolder("folder",1)).thenReturn(folder);
		Folder f=mockedUser.createNewFolder("folder",1);
		assertTrue((f.getClass().toString()).equals("class model.Folder"));
	
	}
	/**
	 * This tests the folder exists method
	 */
	@Test
	public void testFolderExists() {
		when(mockedUser.folderExists("folder")).thenReturn(true);
		assertTrue(mockedUser.folderExists("folder"));
	}
	/**
	 * This test case tests the get folder level
	 */
	@Test
	public void testGetFolderLevel() {
		when(mockedUser.getFolderLevel(0)).thenReturn(1);
		assertEquals(1,(mockedUser.getFolderLevel(0)));
	}
	/**
	 * This test case tests the get folder method with an int argument
	 * @throws ModelException
	 */
	@Test
	public void testGetFolderInt() throws ModelException {
		when(mockedUser.getFolder(0)).thenReturn(folder);
		Folder f=mockedUser.getFolder(0);
		assertTrue((f.getClass().toString()).equals("class model.Folder"));
	}
	/**
	 * This test case tests the get folder method with a string argument
	 */
	@Test
	public void testGetFolderString() {
		when(mockedUser.getFolder("folder a")).thenReturn(folder);
		Folder f=mockedUser.getFolder("folder a");
		assertTrue((f.getClass().toString()).equals("class model.Folder"));
	}
	/**
	 * This test case tests the get parent folder method
	 */
	@Test
	public void testGetParentFolder() {
		when(mockedUser.getParentFolder(1)).thenReturn(folder);
		Folder f=(mockedUser.getParentFolder(1));
		assertTrue((f.getClass().toString()).equals("class model.Folder"));
	}
	/**
	 * This test case tests the get child folders method
	 */
	@Test
	public void testGetChildFolders() {
		when(mockedUser.getChildFolders(1)).thenReturn(liftOfFolders);
		ArrayList<Folder> f=(ArrayList<Folder>) (mockedUser.getChildFolders(1));
		assertTrue((f.getClass().toString()).equals("class java.util.ArrayList"));
	}
	/**
	 * This test case tests the get folders method
	 */
	@Test
	public void testGetFolders() {
		assertEquals("class java.util.ArrayList",(user.getFolders().getClass().toString()));
	}

	/**
	 * This test case tests the set folders method
	 */
	@Test
	public void testSetFolders() {
		liftOfFolders.add(new Folder("folder b",1,1));
		user.setFolders(liftOfFolders);
		assertEquals(1,user.getFolders().size());
	}
	/**
	 * This test case tests the create new token method
	 * @throws ModelException
	 */
	@Test
	public void testCreateNewToken() throws ModelException {
		
		when(mockedUser.createNewToken("key", "value")).thenReturn(token);
		Token result=(mockedUser.createNewToken("key", "value"));
		assertTrue((result.getClass().toString()).equals("class model.Token"));
	
	}
	/**
	 * This test case tests the create new template method
	 * @throws ModelException
	 */
	@Test
	public void testCreateNewTemplate() throws ModelException {
		when(mockedUser.createNewTemplate("title", "body")).thenReturn(template);
		assertTrue((mockedUser.createNewTemplate("title", "body").getClass().toString()).equals("class model.Template"));
	}
	/**
	 * This test case tests the template exists method
	 */
	@Test
	public void testTemplateExists() {
		when(mockedUser.templateExists("title")).thenReturn(true);
		assertEquals(true,(mockedUser.templateExists("title")));
	}
	/**
	 * This test case tests the get template method with int argument
	 */
	@Test
	public void testGetTemplateInt() {
		when(mockedUser.getTemplate(0)).thenReturn(template);
		assertTrue((mockedUser.getTemplate(0).getClass().toString()).equals("class model.Template"));
	}
	/**
	 * This test case tests the get template method with a string argument
	 */
	@Test
	public void testGetTemplateString() {
		when(mockedUser.getTemplate("temp1")).thenReturn(template);
		assertTrue((mockedUser.getTemplate("temp1").getClass().toString()).equals("class model.Template"));
	}
	/**
	 * This test case tests the get templates method
	 */
	@Test
	public void testGetTemplates() {
		assertEquals(0,user.getTemplates().size());
	}

	/**
	 * This test case tests the set templates method
	 */
	@Test
	public void testSetTemplates() {
		user.setTemplates(listOfTemplates2);
		assertEquals(0,user.getTemplates().size());
	}
	/**
	 * This test case tests the get template hash map method
	 */
	@Test
	public void testGetTemplateHashMap() {
		HashMap<String,String> templatesHash=new HashMap<String,String>();
		when(mockedUser.getTemplateHashMap()).thenReturn(templatesHash);
		assertTrue((mockedUser.getTemplateHashMap().getClass().toString()).equals("class java.util.HashMap"));
	}
	/**
	 * This test case tests the create new meeting method
	 * @throws ModelException
	 */
	@Test
	public void testCreateNewMeeting() throws ModelException {
		when(mockedUser.createNewMeeting(null, null, null, null, null, null)).thenReturn(meeting);
		assertTrue((mockedUser.createNewMeeting(null, null, null, null, null, null).getClass().toString()).equals("class model.Meeting"));
		
	}
	/**
	 * This test case tests the get meeting method with an int argument
	 */
	@Test
	public void testGetMeetingInt() {
		when(mockedUser.getMeeting(0)).thenReturn(meeting);
		assertEquals((mockedUser.getMeeting(0)).getClass().toString(),"class model.Meeting");
	}
	/**
	 * This test case tests the get meetings with a string argument method
	 */
	@Test
	public void testGetMeetingString() {
		when(mockedUser.getMeeting("meeting")).thenReturn(liftOfMeetings);
		assertTrue(((mockedUser.getMeeting("meeting")).getClass().toString()).equals("class java.util.ArrayList"));
		
	}
	/**
	 * This test case tests the get meetings method
	 */
	@Test
	public void testGetMeetings() {
		assertEquals(0,user.getMeetings().size());
	}
	/**
	 * This test case tests the set meetings method
	 */
	@Test
	public void testSetMeetings() {
		user.setMeetings(listOfMeetings2);
		assertEquals(0,user.getMeetings().size());
	}
	/**
	 * This test case tests the create new filter method
	 * @throws ModelException
	 */
	@Test
	public void testCreateNewFilter() throws ModelException {
	when(mockedUser.createNewFilter(null, null, null, null, null, 0)).thenReturn(filter);
	assertEquals(((mockedUser.createNewFilter(null, null, null, null, null, 0)).getClass().toString()),"class model.Filter");
	
	}
	/**
	 * This test case tests the get filter method with itn argument
	 */
	@Test
	public void testGetFilterInt() {
		when(mockedUser.getFilter(0)).thenReturn(filter);
		assertEquals(((mockedUser.getFilter(0)).getClass().toString()),"class model.Filter");
	}
	/**
	 * This test case tests the get filters method with string argument
	 */
	@Test
	public void testGetFilterString() {
		when(mockedUser.getFilter("filter1")).thenReturn(filter);
		assertEquals(((mockedUser.getFilter("filter1")).getClass().toString()),"class model.Filter");
	}
	/**
	 * This test case tests the get filters method
	 */
	@Test
	public void testGetFilters() {
		assertEquals(0,user.getFilters().size());
	}
	/**
	 * This test case tests the set filters method
	 */
	@Test
	public void testSetFilters() {
		user.setFilters(liftOfFilters);
		assertEquals(0,user.getFilters().size());
	}
	/**
	 * This test case tests the search email method with four string arguments
	 */
	@Test
	public void testSearchEmailsStringStringStringString() {
		when(mockedUser.searchEmails("to", "from", "subject", "body")).thenReturn(listOfEmails);
		assertEquals(0,mockedUser.searchEmails("to", "from", "subject", "body").size());
	}
	/**
	 * This test case tests the search emails method with two strings arguments
	 */
	@Test
	public void testSearchEmailsStringString() {
		when(mockedUser.searchEmails("str", "str2")).thenReturn(listOfEmails);
		assertEquals(0,(mockedUser.searchEmails("str", "str2").size()));
	}
	/**
	 * This test case tests the get email method
	 */
	@Test
	public void testGetEmail() {
		when(mockedUser.getEmail(1)).thenReturn(email);
		assertEquals((mockedUser.getEmail(1)).getClass().toString(),"class model.Email");
	}
	/**
	 * This test case tests the check if dates overlap method
	 */
	@Test
	public void testCheckIfDatesOverlap() {
		assertFalse(user.checkIfDatesOverlap(meeting));
	}

}
